package com.fin.zw.aiqas.service;

import com.fin.zw.aiqas.entity.*;
import com.fin.zw.aiqas.enums.*;
import com.fin.zw.aiqas.repository.DepartmentRepository;
import com.fin.zw.aiqas.repository.InspectionDetailRepository;
import com.fin.zw.aiqas.repository.InspectionRepository;
import com.fin.zw.aiqas.repository.TaskInfoRepository;
import com.fin.zw.aiqas.util.BadRequestException;
import com.fin.zw.aiqas.util.FileUtil;
import com.fin.zw.aiqas.util.VideoUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.thymeleaf.util.ListUtils;

import java.io.File;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

@Service("taskInfoJobService")
public class TaskInfoJobService {

    private final static Logger log = LoggerFactory.getLogger(TaskInfoJobService.class);

    @Autowired
    private TaskInfoRepository taskInfoRepository;

    @Autowired
    private InspectionRepository inspectionRepository;

    @Autowired
    private InspectionDetailRepository inspectionDetailRepository;

    @Autowired
    private DepartmentRepository departmentRepository;

    @Autowired
    private QcTaskInfoService qcTaskInfoService;

    /**
     * 从List中随机出n个对象
     *
     * @param list
     * @param num
     * @return
     */
    private static List<File> createRandomList(List<File> list, int num) {
        List<Integer> number =new ArrayList<>();
        List<File> listNew = new ArrayList();
        if (list.size() <= num) return list;
        while (number.size() < num) {
            int random = (int) (Math.random() * list.size());
            if (!number.contains(random)) {
                number.add(random);
                log.info(random + "随机抽取的对象：" + list.get(random));
                listNew.add(list.get(random));
            }
        }
        return listNew;
    }

    /**
     * 质检结果处理
     *
     * @param taskInfo
     * @param voiceNum
     * @return
     */
    public InspectionInfo saveInspection(TaskInfo taskInfo, Integer voiceNum) {
        InspectionInfo inspectionInfo = new InspectionInfo();
        inspectionInfo.setTaskInfo(taskInfo);
        inspectionInfo.setRunDate(new Date());
        inspectionInfo.setVoiceNum(voiceNum);
        inspectionInfo.setComplateNum(0);
        inspectionInfo.setTaskStatus(InspTask.EXCUTING);
        inspectionInfo.setHitNum(0);
        inspectionInfo.setHitScale(new BigDecimal(0));
        inspectionInfo.setCreateTime(new Date());
        inspectionInfo.setInspectionBatch(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));
        return inspectionInfo;
    }

    /**
     * 处理质检明细
     *
     * @param taskInfo
     * @param urls
     * @return
     */
    public List<InspectionDetail> saveInspectionDetail(TaskInfo taskInfo, List<File> urls, InspectionInfo inspectionInfo, Map<String, Integer> map) {
        List<InspectionDetail> list = new ArrayList<>();
        for (File file : urls) {
            InspectionDetail inspectionDetail = new InspectionDetail();
            inspectionDetail.setInspectionInfo(inspectionInfo);
            inspectionDetail.setTaskInfo(taskInfo);
            inspectionDetail.setVoiceUrl(file.getPath());
            inspectionDetail.setHitStatus(HitStatus.MISS);
            //设置客服编号和部门
            setDetailProperty(file, inspectionDetail);
            //设置质检状态
            inspectionDetail.setQualityStatus(QualityStatus.READY);//就绪状态
            inspectionDetail.setCreateTime(new Date());
            if (map.containsKey(file.getPath())) {
                inspectionDetail.setVoiceLength(map.get(file.getPath()));
            } else {
                inspectionDetail.setVoiceLength(0);
            }
            list.add(inspectionDetail);
        }
        return list;
    }


    /**
     * 根据文件路径解析客户编号和机构
     *
     * @param file
     * @param info
     */
    public void setDetailProperty(File file, InspectionDetail info) {

        //从后往前，一次是文件名，日期，座席号，机构......
        String[] pathSplit = file.getPath().split(File.separator);
        int pLen = pathSplit.length;
        String agent = pLen > 2 ? pathSplit[pLen-3] : "";      //获取座席号
        String departCode = pLen > 3 ? pathSplit[pLen-4] : "";        //到机构目录路径
        String fname = pLen > 1 ? pathSplit[pLen-2] : "";      //获取座席号
        String scode = pLen > 0 ? pathSplit[pLen-1] : "";        //到机构目录路径
        info.setServiceCode(scode);
        info.setFileName(fname);
        info.setServiceExt(agent);
        Optional<Department> optional = departmentRepository.findOne(QDepartment.department.code.eq(departCode));
        if (optional.isPresent()) {
            info.setDepartment(optional.get());
        }
    }


    public String getFile(String path) {
        File file = new File(path);
        return file.getParent();
    }

    @Async
//    @Transactional
    public void sendTaskInfo(Long taskId) {
        log.info("开始状态数据" + taskId);
        Optional<TaskInfo> optional = taskInfoRepository.findById(taskId);
        if (!optional.isPresent()) {
            throw new BadRequestException("", "推送的任务信息不存在！+");
        }
        TaskInfo taskInfo = optional.get();
        List<File> urls = FileUtil.getAllFiles(taskInfo.getTaskFilePath());
        taskInfo.setStartTime(new Date());
        if (ListUtils.isEmpty(urls)) {
            taskInfo.setRunStatus(TaskStatus.FINISH);
            taskInfo.setEndTime(new Date());
            taskInfoRepository.save(taskInfo);
        } else {
            Map<String, Integer> map = new HashMap<>();
            List<File> results = filtrateTaskInfoFile(urls, taskInfo, map);
            //计算抽检数量
            Double number = results.size() * taskInfo.getCheckProp().doubleValue() * 0.01;
            int size = number.intValue();
            if (size < 1) { //抽取的文件数量为0
                taskInfo.setEndTime(new Date());
                taskInfo.setRunStatus(TaskStatus.FINISH);
                taskInfoRepository.save(taskInfo);
            } else {
                List<File> files = createRandomList(results, size);
                //保存质检结果
                InspectionInfo info = saveInspection(taskInfo, size);
                info = inspectionRepository.save(info);
                List<InspectionDetail> details = saveInspectionDetail(taskInfo, files, info, map);
                log.info("质检明细保存信息：" + details);
                details = inspectionDetailRepository.saveAll(details);
                qcTaskInfoService.executeTaskInfo(details, taskInfo.getId());
            }
        }
    }


    /**
     * 针对文件条件进行条件过滤
     *
     * @param files
     * @param taskInfo
     * @param map
     * @return
     */
    public List<File> filtrateTaskInfoFile(List<File> files, TaskInfo taskInfo, Map<String, Integer> map) {
        List<File> results = new ArrayList<>();
        for (File file : files) {
            try {
                Map<String, Object> audioInfo =  VideoUtil.getAudioInfo(file);
                Long voiceLength = (long)audioInfo.get("duration");
                BigDecimal voice = new BigDecimal(voiceLength);
                if (taskInfo.getDurationLogic().equals(LogicalCalculus.LARGER)) {  //大于
                    if (voice.compareTo(taskInfo.getNum()) == 1) {
                        results.add(file);
                        map.put(file.getPath(), voiceLength.intValue());
                    }
                } else if (taskInfo.getDurationLogic().equals(LogicalCalculus.LESS)) { //小于
                    if (voice.compareTo(taskInfo.getNum()) == -1) {
                        results.add(file);
                        map.put(file.getPath(), voiceLength.intValue());
                    }
                } else { //自定义
                    if (voice.compareTo(taskInfo.getNum()) == 1 && voice.compareTo(taskInfo.getEndNum()) == -1) {
                        results.add(file);
                        map.put(file.getPath(), voiceLength.intValue());
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return results;
    }
}
